package org.juiceshop.musi;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;


public abstract class MusicContainer extends MusicObject implements Iterable<MusicObject> {

	private final List<MusicObject> _content = new LinkedList<MusicObject>();
	private final MusicContainer _parent;
	
	
	public MusicContainer (MusicObject ...args) {
		this(null,args);
	}
	
	public MusicContainer (MusicContainer parent, MusicObject ...args) {
		_parent = parent;
		add(args);
	}
	
		
	public void add(MusicObject ...args) {
		for (MusicObject arg : args) {
			add(arg);
		}
	}
	
	@Override
	public Iterator<MusicObject> iterator() {
		return _content.iterator();
	}

	public void add(MusicObject obj) {
		if (this.getClass().isInstance(obj)) {
			throw new IllegalArgumentException("Cannot add "+obj.getClass().getName()+" to "+this.getClass().getName());
		}
		MusicObject copy = obj.copy();
		copy.setParent(this);
		_content.add(copy);
	}
		
	public MusicObject get(int index) {
		if (index<0 || index>=_content.size()) {
			throw new IndexOutOfBoundsException("Cannot get element # "+index+" of "+size()+" elements.");
		}
		return _content.get(index);
	}
	
	public MusicObject getAt(int index) {
		return get(index);
	}
		
	
	@Override
	public int size() {
		return _content.size();
	}
	
	    
	@Override
	public MusicContainer transpose(int steps) {
		for (int i=0; i<size(); i++) {
			this.replaces()
		}
	}

		
	@Override
	public MusicContainer copy() {
		MusicContainer copy = emptyCopy();
		for (MusicObject obj : this) {
			copy.add(obj);
		}
		return copy;
	}
		
	protected String toString(char delimiter) {
		return "("+Util.join(this,delimiter)+")";
	}

    public List<MusicObject> asList() {
    	return Collections.unmodifiableList(_content);
    }
	
}
